<template>
  <div class="image-processer">
    <el-dialog v-model="showModal" title="裁剪图片">
      <div class="image-cropper">
        <img id="processed-image" ref="cropperImg" :src="baseImageUrl" />
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showModal = false">取消</el-button>
          <el-button type="primary" @click="handleOk">确认</el-button>
        </span>
      </template>
    </el-dialog>
    <div class="image-preview" :style="{ backgroundImage: backgroundUrl }" :class="{ extraHeight: showDelete }"></div>
    <div class="image-process">
      <styled-uploader @success="handleFileUploaded"></styled-uploader>
      <el-button :icon="Scissor" @click="showModal = true">裁剪图片</el-button>
      <el-button v-if="showDelete" :icon="Delete" type="danger" @click="handleDelete">删除图片</el-button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { Scissor, Delete } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import Cropper from 'cropperjs'
// import { UploadResp } from '@/extraType'

interface CropDataProps {
  x: number
  y: number
  width: number
  height: number
}

const props = withDefaults(defineProps<{ modelValue: string; ratio?: number; showDelete?: boolean }>(), {
  modelValue: '',
  showDelete: false
})
const emit = defineEmits(['change', 'uploaded'])

const showModal = ref(false)
const backgroundUrl = computed(() => `url(${props.modelValue})`)
// 如果使用阿里云 OSS处理图片，需要每次重新渲染原图，所以要把 ？后面的参数去掉
const baseImageUrl = computed(() => props.modelValue.split('?')[0])
const cropperImg = ref<null | HTMLImageElement>(null)
let cropper: Cropper
let cropData: CropDataProps | null = null

watch(showModal, async newValue => {
  if (newValue) {
    await nextTick()
    // console.log(cropperImg.value)
    cropper = new Cropper(cropperImg.value, {
      crop(event) {
        // console.log(event)
        const { x, y, width, height } = event.detail
        cropData = {
          x: Math.floor(x),
          y: Math.floor(y),
          width: Math.floor(width),
          height: Math.floor(height)
        }
      }
    })
  } else {
    if (cropper) {
      cropper.destroy()
    }
  }
})

const handleOk = () => {
  if (cropData) {
    // 第一种裁剪方式：使用阿里云 OSS 提供的图片处理方式
    const { x, y, width, height } = cropData
    const cropperURL = baseImageUrl.value + `?x-oss-process=image/crop,x_${x},y_${y},w_${width},h_${height}`
    emit('change', cropperURL)
    // 第二种方式：不使用阿里云 OSS，拿到截图图片再次上传的处理方法
    // 获取到 HTMLCanvasElement，Canvas 上有 toBlob，toDataURL 方法
    // cropper.getCroppedCanvas().toBlob(blob => {
    //   if (blob) {
    //     const formData = new FormData()
    //     formData.append('croppedImage', blob, 'test.png')
    //     axios
    //       .post('http://localhost:7001/api/utils/upload-img', formData, {
    //         headers: {
    //           'Content-Type': 'multipart/form-data'
    //         }
    //       })
    //       .then(res => {
    //         console.log(res.data.data.url)
    //         emit('change', res.data.data.url)
    //         showModal.value = false
    //       })
    //       .catch(() => {
    //         showModal.value = false
    //       })
    //   }
    // })
  }
  showModal.value = false
}

const handleFileUploaded = (data: { url: string; file: File }) => {
  ElMessage.success('上传成功')
  emit('change', data.url)
  emit('uploaded', data)
}
const handleDelete = () => {
  emit('change', '')
}
</script>
<style lang="scss" scoped>
.image-processer {
  display: flex;
  justify-content: space-between;
}
.image-preview {
  width: 150px;
  height: 84px;
  border: 1px dashed #e6ebed;
  background: no-repeat 50% / contain;
}
.image-preview.extraHeight {
  height: 110px;
}
.image-process {
  padding: 5px 0;
  margin-left: 10px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.image-cropper {
  height: 540px;
  img {
    display: block;
    /* This rule is very important, please don't ignore this */
    max-width: 100%;
  }
}
</style>
